#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Purpose: Test Field classes
# Created: 01/22/2009
# $Id $
# Copyright (c) 2008,2009 by University College London
# Authors:
# Didrik Pinte --<dpinte@dipole-consulting.com>
#
# This program is free software under the GPL (>=v2)
# Read the file COPYING coming with HydroPlatform for details.

from datetime import date
from numpy import array, random
import unittest
import wx
import wx.grid

import support
support.init_hydroplatform()

from hydroplatform.model.network import Node, Project, NodeType
from hydroplatform.model import units
from hydroplatform.ui import fields
from hydroplatform.model.fields import TableCol


class TestTraits(unittest.TestCase):
    
    def setUp(self):
        session = support.get_dbsession()
        support.load_sample_network1(session)
        self.project = session.query(Project).first()
    
    
    def test_parameter(self):
        p = fields.Parameter()
        p.value = 152
        p.unit = "kWh"
        
    def test_group(self):
        from numpy.random import random
            
        #parameters
        p = fields.Parameter(name="Production factor", value=156, unit="kWh")
        p1 = fields.Parameter(name="Frequency", value=2, unit="day")
        ll = [p, p1]
        
        
        #timeseries
        ts1 = fields.TimeSerie(name="bc1", data=random((10000,1)))
        ts2 = fields.TimeSerie(name="bc2")
        
        #tables
        tbl1 = fields.Table(name="reservoir", 
                            colNames=['volume', 'surface', 'height'],
                            colUnits=['hm3', 'km2', 'm'],
                            data = random((25,3)))
        
        
        datagrp = fields.DataGroup(name='default', 
                                   parameters=[p, p1], 
                                   timeseries=[ts1, ts2],
                                   tables=[tbl1])
        #owner = fields.Owner(name='general', group=datagrp)
        #owner.configure_traits()
                
    def test_timeserie(self):
        ts = fields.TimeSerie()
        ts.data = random.random((1000,1))
        ts.unit
        

    def test_season(self):
        season = fields.SeasonalParameter(fromd = date(2009,01,01),
                                           tod = date(2010,12,31),
                                           step = units.MONTHLY,
                                           horizon = False)

        self.assertEquals(len(season.dates), 12)
        season.horizon = True
        self.assertEquals(len(season.dates), 24)
        
        season.configure_traits()
        
    def test_objectfield_updates(self):
        ts = fields.TimeSerie()
        ob = fields.ObjectField(name="undef",
                                ftype = "Time-Series",
                                finst = ts,
                                groups = ['1', '2', '3'],
                                project = self.project)
       
        # check everything is False
        self.assertFalse(ob._configupdated)
        self.assertFalse(ob.finst._configupdated)
        # update the name
        ob.name = "great name"
        # check it is updated
        self.assertTrue(ob.finst._configupdated)
        self.assertTrue(ob._configupdated)
        # reset
        ob._configupdated = False
        self.assertFalse(ob._configupdated)
        self.assertFalse(ob.finst._configupdated)
        
       # update the group
        ob.group = "2"
        # check it is updated
        self.assertTrue(ob.finst._configupdated)
        self.assertTrue(ob._configupdated)
        # reset
        ob._configupdated = False
        self.assertFalse(ob._configupdated)
        self.assertFalse(ob.finst._configupdated)
        
        # update the ftype
        ob.ftype = "Parameter"
        # check it is updated
        self.assertTrue(ob.finst._configupdated)
        self.assertTrue(ob._configupdated)
        # reset
        ob._configupdated = False
        self.assertFalse(ob._configupdated)
        self.assertFalse(ob.finst._configupdated)
 
        
    def test_field_table(self):
        fd = fields.Table()
        ob = fields.ObjectField(name="undef",
                                ftype = "Table",
                                finst = fd,
                                groups = ['1', '2', '3'])       
        
        col1 = TableCol(name="col1", unit="kWh", format="binary")
        
        # check everything is False
        self.assertFalse(ob._configupdated)
        self.assertFalse(fd._configupdated)
        # update the ts
        fd.columns.append(col1)
        # check it is updated
        self.assertTrue(fd._configupdated)
        self.assertTrue(ob._configupdated)
        
        # reset
        ob._configupdated = False
        self.assertFalse(ob._configupdated)
        self.assertFalse(fd._configupdated)
        
        # Test column name update
        col1.name = u"test"
        # check it is updated
        self.assertTrue(fd._configupdated)
        self.assertTrue(ob._configupdated)
        self.assertEqual(fd.columns[0].name, u"test")
        
        # reset
        ob._configupdated = False
        self.assertFalse(ob._configupdated)
        self.assertFalse(fd._configupdated)
        
        # Test column format update
        col1.format = u"float"
        # check it is updated
        self.assertTrue(fd._configupdated)
        self.assertTrue(ob._configupdated)
        self.assertEqual(fd.columns[0].format, u"float")
        
        # reset
        ob._configupdated = False
        self.assertFalse(ob._configupdated)
        self.assertFalse(fd._configupdated)
        
        # Test column unit update
        col1.unit = u"m3"
        # check it is updated
        self.assertTrue(fd._configupdated)
        self.assertTrue(ob._configupdated)
        self.assertEqual(fd.columns[0].unit, u"m3")
        
        # reset
        ob._configupdated = False
        self.assertFalse(ob._configupdated)
        self.assertFalse(fd._configupdated)        
        
        # Test column added
        fd.columns.append(TableCol(name="col2", unit="kWh", format="binary"))
        # check it is updated
        self.assertTrue(fd._configupdated)
        self.assertTrue(ob._configupdated)
        self.assertEqual(len(fd.columns), 2)
        
        # reset
        ob._configupdated = False
        self.assertFalse(ob._configupdated)
        self.assertFalse(fd._configupdated)                
        
        # Test column removed
        fd.columns.remove(col1)
        # check it is updated
        self.assertTrue(fd._configupdated)
        self.assertTrue(ob._configupdated)
        self.assertEqual(len(fd.columns), 1)
        
        # reset
        ob._configupdated = False
        self.assertFalse(ob._configupdated)
        self.assertFalse(fd._configupdated)          
        
        # Test column replaced
        fd.columns[0] = TableCol(name="newcol2", unit="m", format="integer")
        # check it is updated
        self.assertTrue(fd._configupdated)
        self.assertTrue(ob._configupdated)
        self.assertEqual(len(fd.columns), 1)
        
        # reset
        ob._configupdated = False
        self.assertFalse(ob._configupdated)
        self.assertFalse(fd._configupdated)                  
        
        
    def test_field_parameter_updates(self):
        fd = fields.Parameter()
        ob = fields.ObjectField(name="undef",
                                ftype = "Parameter",
                                finst = fd,
                                groups = ['1', '2', '3'])
       
        # check everything is False
        self.assertFalse(ob._configupdated)
        self.assertFalse(fd._configupdated)
        # update the ts
        fd.format = "binary"
        # check it is updated
        self.assertTrue(fd._configupdated)
        self.assertTrue(ob._configupdated)
        
        # reset
        ob._configupdated = False
        self.assertFalse(ob._configupdated)
        self.assertFalse(fd._configupdated)
        # update the ts
        fd.unit = "kWh"
        # check it is updated
        self.assertTrue(fd._configupdated)
        self.assertTrue(ob._configupdated) 
        
        # reset
        ob._configupdated = False
        self.assertFalse(ob._configupdated)
        self.assertFalse(fd._configupdated)
        # update the ts
        fd.shared = True
        # check it is updated
        self.assertTrue(fd._configupdated)
        self.assertTrue(ob._configupdated) 
 
        
    def test_field_timeserie_updates(self):
        ts = fields.TimeSerie()
        ob = fields.ObjectField(name="undef",
                                ftype = "Time-Series",
                                finst = ts,
                                groups = ['1', '2', '3'])
       
        # check everything is False
        self.assertFalse(ob._configupdated)
        self.assertFalse(ts._configupdated)
        # update the ts
        ts.format = "binary"
        # check it is updated
        self.assertTrue(ts._configupdated)
        self.assertTrue(ob._configupdated)
        # reset
        ob._configupdated = False
        self.assertFalse(ob._configupdated)
        self.assertFalse(ts._configupdated)
        
        # update the ts
        ts.unit = "kWh"
        # check it is updated
        self.assertTrue(ts._configupdated)
        self.assertTrue(ob._configupdated)
        # reset
        ob._configupdated = False
        self.assertFalse(ob._configupdated)
        self.assertFalse(ts._configupdated)
        
        # update the ts
        ob.name = "great name"
        # check it is updated
        self.assertTrue(ts._configupdated)
        self.assertTrue(ob._configupdated)
        # reset
        ob._configupdated = False
        self.assertFalse(ob._configupdated)
        self.assertFalse(ts._configupdated)        

    def test_field_seasonal_parameter_updates(self):
        fd = fields.SeasonalParameter(fromd=self.project.horizon_from,
                                      tod= self.project.horizon_to,
                                      step=self.project.time_step,
                                      )
        
        self.assertFalse(fd._configupdated)
        
        ob = fields.ObjectField(name="undef",
                                ftype = "Seasonal Parameter",
                                finst = fd,
                                groups = ['1', '2', '3'],
                                group="1")
       
        # check everything is False
        self.assertFalse(ob._configupdated)
        self.assertFalse(fd._configupdated)
        
        # update the field
        fd.format = "binary"
        # check it is updated
        self.assertTrue(fd._configupdated)
        self.assertTrue(ob._configupdated)
        
        # reset
        ob._configupdated = False
        self.assertFalse(ob._configupdated)
        self.assertFalse(fd._configupdated)
        # update the fd
        fd.unit = "kWh"
        # check it is updated
        self.assertTrue(fd._configupdated)
        self.assertTrue(ob._configupdated) 
        
        # reset
        ob._configupdated = False
        self.assertFalse(ob._configupdated)
        self.assertFalse(fd._configupdated)
        # update the fd
        fd.shared = True
        # check it is updated
        self.assertTrue(fd._configupdated)
        self.assertTrue(ob._configupdated)         
        
        # reset
        ob._configupdated = False
        self.assertFalse(ob._configupdated)
        self.assertFalse(fd._configupdated)
        # update the ts
        fd.horizon = True
        # check it is updated
        self.assertTrue(fd._configupdated)
        self.assertTrue(ob._configupdated)  
        
         # reset
        ob._configupdated = False
        self.assertFalse(ob._configupdated)
        self.assertFalse(fd._configupdated)
        # update the fd
        fd.starting_date = date.today()
        # check it is updated
        self.assertTrue(fd._configupdated)
        self.assertTrue(ob._configupdated)         
        
         # reset
        ob._configupdated = False
        self.assertFalse(ob._configupdated)
        self.assertFalse(fd._configupdated)
        # update the fd
        fd.sstep = units.YEARLY
        # check it is updated
        self.assertTrue(fd._configupdated)
        self.assertTrue(ob._configupdated)                 
        
         # reset
        ob._configupdated = False
        self.assertFalse(ob._configupdated)
        self.assertFalse(fd._configupdated)
        # update the fd
        fd.amount = 1000
        # check it is updated
        self.assertTrue(fd._configupdated)
        self.assertTrue(ob._configupdated)        
        
         # reset
        ob._configupdated = False
        self.assertFalse(ob._configupdated)
        self.assertFalse(fd._configupdated)
        # update the fd
        fd.step_code = u"a = 2"
        # check it is updated
        self.assertTrue(fd._configupdated)
        self.assertTrue(ob._configupdated)           